﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;

namespace EvoBoost.Core
{
	[Serializable]
	public abstract class SplitBase<T>
	{
		private readonly ReadOnlyCollection<ISplitParameterDescription> parameterDescriptionsReadOnly;

		private readonly List<ISplitParameterDescription> parameterDescriptions;

		protected SplitBase(IEnumerable<ISplitParameterDescription> parameterDescriptions)
		{
			this.parameterDescriptions = new List<ISplitParameterDescription>(parameterDescriptions);
			this.parameterDescriptionsReadOnly = new ReadOnlyCollection<ISplitParameterDescription>(this.parameterDescriptions);
		}

		public ReadOnlyCollection<ISplitParameterDescription> ParameterDescriptions
		{
			get { return this.parameterDescriptionsReadOnly; }
		}
		
		public abstract double Calculate(T sampleProperties, IList<double> parameterValues);
		
		public double[] GenerateRandomParameters()
		{
			double[] result = new double[parameterDescriptions.Count];
			for (int i = 0; i < parameterDescriptions.Count; ++i)
				result[i] = this.parameterDescriptions[i].GenerateRandom();

			return result;
		}

		public double[] PerturbParameters(IList<double> parameterValues)
		{
			if (parameterValues.Count != this.parameterDescriptions.Count)
				throw new ArgumentException(string.Format(
					CultureInfo.CurrentCulture,
					"Invalid amount of parameters given (should be {0}).",
					this.parameterDescriptions.Count));

			double[] result = new double[parameterDescriptions.Count];
			for (int i = 0; i < this.parameterDescriptions.Count; ++i)
				result[i] = this.parameterDescriptions[i].Perturb(parameterValues[i]);

			return result;
		}
	}
}
